# -*- coding: utf-8 -*-

"""
  @author: 唐黎琦
  @date: 2022/6/16 14:02
  @python version: 3.6 
  
  ---------------------------------------
  @desc: PyCharm => python设计模式实现
"""


# ============================  通过 __new__ 方法实现单例  ============================
class Log:
    """
    通过 __new__ 方法实现一个单例类
    通过 _instance 属性用来保证实例唯一性
    """

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            cls._instance = super().__new__(cls)
        return cls._instance


# ============================  通过 函数装饰器 实现单例  ============================

def singleton(cls):
    """
    通过函数装饰器来实现一个类
    """
    _instance = dict()

    def _(*args, **kwargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kwargs)
        return _instance[cls]

    return _


@singleton
class Log1:
    def __init__(self):
        print("aaa")


# ============================  通过 类装饰器 实现单例  ============================

class Singleton:
    def __init__(self, cls):
        self._cls = cls
        self._instance = {}

    def __call__(self):
        if self._cls not in self._instance:
            self._instance[self._cls] = self._cls
        return self._instance[self._cls]


@Singleton
class Log2:
    def __init__(self):
        print("aaa")


# ============================  通过 模块化 实现单例  ============================

class Log3:
    """
    log = Log3()
    其他模块通过引入已经实例好log对象,实现单例
    from . import log
    """
    pass


# ============================  通过 双重检测 实现单例  ============================
from threading import Lock


class Log4:
    """
    通过一个多线程锁保证同一时刻最多只有一个线程能创建实例
    不能通过 new 方法创建实例
    """
    _lock = Lock()

    def __new__(cls, *args, **kwargs):
        msg = "Cann't new a SingletonSample class, please use get_instance method!"
        raise NotImplementedError(msg)

    @classmethod
    def get_instance(cls):
        if not hasattr(cls, "_instance"):
            with cls._lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = super().__new__(cls)
        return cls._instance
